package network;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: ws
 * Date: 2023-07-07
 * Time: 13:08
 */
public class TcpEchoServer {
    private ServerSocket serverSocket = null;//提供长时间的服务，不必很快关闭

    public TcpEchoServer(int port) throws IOException {
        serverSocket = new ServerSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动");
//        while (true) {
//            Socket clientSocket = serverSocket.accept();
//            //创建新的线程，用来服务多个客户端
//            Thread t = new Thread(() -> {
//                try {
//                    processConnection(clieentSocket);
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            });
//            t.start();
//        }
        //线程池改进
        ExecutorService executorService = Executors.newCachedThreadPool();
        while (true) {
            Socket clientSocket = serverSocket.accept();
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        processConnection(clientSocket);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    //处理连接，根据请求计算响应，把响应返回客户端
    private void processConnection(Socket clientSocket) throws IOException {
        System.out.printf("[%s : %d] 客户端上线\n", clientSocket.getInetAddress().toString(), clientSocket.getPort());
        //try()中允许多个流对象，需要用;隔开
        try (InputStream inputStream = clientSocket.getInputStream();
             OutputStream outputStream  =clientSocket.getOutputStream()){
            //规定请求/响应的格式
            //1. 每个请求都是字符串（文本数据）
            //2. 请求和请求之间，使用\n分割
            //包装成字符流，同时借用Scanner的方法
            Scanner scanner = new Scanner(inputStream);
            //包装成字符流，同时借用PrintWriter的方法
            PrintWriter printWriter = new PrintWriter(outputStream);
            while (true) {
                //1. 读取请求
                if (!scanner.hasNext()) {
                    //结尾，结束
                    System.out.printf("[%s : %d] 客户端下线\n", clientSocket.getInetAddress().toString(), clientSocket.getPort());
                    break;
                }
                //读取一段字符串
                String request = scanner.next();
                //2. 根据请求计算响应
                String response = process(request);
                //3. 把响应写回客户端，不要忘了，响应也要写\n
                printWriter.println(request);
                //刷新缓冲区
                printWriter.flush();
                System.out.printf("[%s : %d] req: %s; resp: %s\n", clientSocket.getInetAddress().toString(), clientSocket.getPort(), request, response);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //clientSocket只是给一个连接提供服务，用完结束
            clientSocket.close();
        }
    }

    private String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer server = new TcpEchoServer(9090);
        server.start();
    }
}
